import { useCallback, useEffect, useRef, useState } from 'react'

export function useSiderResize(initialWidth = 240, minWidth = 180) {
  const [width, setWidth] = useState(initialWidth)
  const [isResizing, setIsResizing] = useState(false)
  const startXRef = useRef(0)
  const startWidthRef = useRef(0)
  const maxWidthRef = useRef(320)
  const rafIdRef = useRef<number | null>(null)
  const pendingXRef = useRef<number | null>(null)

  const end = useCallback(() => {
    if (!isResizing) return
    setIsResizing(false)
    document.body.style.userSelect = ''
    document.body.style.cursor = ''
    window.removeEventListener('mousemove', move)
    window.removeEventListener('mouseup', end)
    window.removeEventListener('blur', end)
    window.removeEventListener('mouseleave', end as any)
    if (rafIdRef.current) {
      cancelAnimationFrame(rafIdRef.current)
      rafIdRef.current = null
    }
    pendingXRef.current = null
  }, [isResizing])

  const move = useCallback(
    (e: MouseEvent) => {
      if (!isResizing) return
      if (e.buttons === 0) {
        end()
        return
      }
      pendingXRef.current = e.clientX
      if (rafIdRef.current == null) {
        rafIdRef.current = requestAnimationFrame(() => {
          rafIdRef.current = null
          const x = pendingXRef.current ?? e.clientX
          const deltaX = x - startXRef.current
          const next = Math.max(
            minWidth,
            Math.min(maxWidthRef.current, startWidthRef.current + deltaX)
          )
          setWidth(next)
        })
      }
    },
    [end, isResizing, minWidth]
  )

  const start = useCallback(
    (e: React.MouseEvent) => {
      if (e.button !== 0) return
      e.preventDefault()
      setIsResizing(true)
      startXRef.current = e.clientX
      startWidthRef.current = width
      maxWidthRef.current = Math.min(420, Math.max(240, Math.floor(window.innerWidth * 0.4)))
      document.body.style.userSelect = 'none'
      document.body.style.cursor = 'col-resize'
      window.addEventListener('mousemove', move)
      window.addEventListener('mouseup', end)
      window.addEventListener('blur', end)
      window.addEventListener('mouseleave', end as any)
    },
    [end, move, width]
  )

  useEffect(() => () => end(), [end])

  return { width, isResizing, handleResizeStart: start }
}
